/**
 *******************************************************************************
 * @FileName  : hid_svc.c
 * @Author    : GaoQiu
 * @CreateDate: 2020-05-18
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */
#include "svc_handle.h"
#include "stack/host/att_uuid.h"
#include "stack/host/dm_api.h"
#include "utils/byte_stream.h"


/**
 * @Name HID Spec Version
 * @{
 */
/*! HID Spec Version: 1.11 */
#define HID_VERSION                   0x0111
/**@}*/

/**
 * @Name HID Report Types
 * @{
 */
#define HID_REPORT_TYPE_INPUT         0x01  /*!< Input type. */
#define HID_REPORT_TYPE_OUTPUT        0x02  /*!< Output type. */
#define HID_REPORT_TYPE_FEATURE       0x03  /*!< Feature type. */
/**@}*/

/**
 * @Name HID Protocol Mode Types
 * @{
 */
#define HID_PROTOCOL_MODE_BOOT        0x00  /*!< Boot mode. */
#define HID_PROTOCOL_MODE_REPORT      0x01  /*!< Report mode. */
/**@}*/

/**
 * @Name HID Control Point Values
 * @{
 */
#define HID_CONTROL_POINT_SUSPEND     0x00  /*!< Suspend. */
#define HID_CONTROL_POINT_RESUME      0x01  /*!< Resume. */
/**@}*/

/*! Max length of the report map value */
#define HID_MAX_REPORT_MAP_LEN        512

/*! Max length of an output report value */
#define HID_MAX_REPORT_LEN            32

/*! Initial length of the report map value */
#define HID_INIT_REPORT_MAP_LEN       1


/**
 *------------------------------------------------------------------------------
 *  HID Attribute table
 *------------------------------------------------------------------------------
 */

/*! Characteristic read permissions */
#ifndef HID_SEC_PERMIT_READ
#define HID_SEC_PERMIT_READ  ATTS_PERMIT_READ//(ATTS_PERMIT_READ | ATTS_PERMIT_READ_ENC) //ATTS_PERMIT_READ //
#endif

/*! Characteristic write permissions */
#ifndef HID_SEC_PERMIT_WRITE
#define HID_SEC_PERMIT_WRITE ATTS_PERMIT_WRITE//(ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC) //ATTS_PERMIT_WRITE //
#endif

/*! HID Report IDs */
#define HIDAPP_KEYBOARD_REPORT_ID         1 //keyboard
#define HIDAPP_REMOTE_REPORT_ID           2 //Consumer
#define HIDAPP_MOUSE_REPORT_ID            3 //mouse

/*! Proprietary Service Declaration */
static const uint8_t hidSvc[] = {UINT16_TO_BYTES(ATT_UUID_HID_SERVICE)};
static const uint16_t hidSvcLen = sizeof(hidSvc);


/*! HID Info Characteristic */
static const uint8_t hidInfoProp[] = {ATT_PROP_READ, UINT16_TO_BYTES(HID_INFO_HDL), UINT16_TO_BYTES(ATT_UUID_HID_INFORMATION)};
static const uint16_t hidInfoPropLen = sizeof(hidInfoProp);

/*! HID Info Value: HID Spec version, country code, flags */
static const uint8_t hidInfoVal[] = {UINT16_TO_BYTES(HID_VERSION), 0x00, 0x00};
static const uint16_t hidInfoValLen = sizeof(hidInfoVal);


/*! HID Report Map Characteristic */
static const uint8_t hidReportMapProp[] = {ATT_PROP_READ, UINT16_TO_BYTES(HID_REPORT_MAP_HDL), UINT16_TO_BYTES(ATT_UUID_HID_REPORT_MAP)};
static const uint16_t hidReportMapPropLen = sizeof(hidReportMapProp);

/* HID Report Map Value */
/* Note: The hidReportMap and hidReportMapLen variables should be defined in the application */
/*! HidApp Report Map (Descriptor) */
static const uint8_t hidReportMap[] =
{
#if 1
	0x05, 0x0c,                    /* Usage Page (Consumer Devices) */
	0x09, 0x01,                    /* Usage (Consumer Control) */
	0xa1, 0x01,                    /* Collection (Application) */
	0x85, HIDAPP_REMOTE_REPORT_ID, /*   report ID (HIDAPP_REMOTE_REPORT_ID) */

	0x15, 0x00,                    /*   Logical Minimum (0) */
	0x25, 0x01,                    /*   Logical Maximum (1) */
	0x09, 0xe9,                    /*   Usage (Volume Up) */
	0x09, 0xea,                    /*   Usage (Volume Down) */
	0x75, 0x01,                    /*   Report Size (1) */
	0x95, 0x02,                    /*   Report Count (2) */
	0x81, 0x06,                    /*   Input (Data, Variable, Relative) */

	0x09, 0xe2,                    /*   Usage (Mute) */
	0x95, 0x01,                    /*   Report Count (1) */
	0x81, 0x06,                    /*   Input (Data, Variable, Relative) */
	0x09, 0xb0,                    /*   Usage (Play) */
	0x95, 0x01,                    /*   Report Count (1) */
	0x81, 0x06,                    /*   Input (Data, Variable, Relative) */
	0x09, 0xb1,                    /*   Usage (Pause) */
	0x95, 0x01,                    /*   Report Count (1) */
	0x81, 0x06,                    /*   Input (Data, Variable, Relative) */
	0x09, 0xb7,                    /*   Usage (Stop) */
	0x95, 0x01,                    /*   Report Count (1) */
	0x81, 0x06,                    /*   Input (Data, Variable, Relative) */
	0x09, 0xb5,                    /*   Usage (Next) */
	0x95, 0x01,                    /*   Report Count (1) */
	0x81, 0x06,                    /*   Input (Data, Variable, Relative) */
	0x09, 0xb6,                    /*   Usage (Previous) */
	0x95, 0x01,                    /*   Report Count (1) */
	0x81, 0x06,                    /*   Input (Data, Variable, Relative) */
	0xc0,                          /* End Collection */

	0x05, 0x01,                    /* Usage Page (Generic Desktop) */
	0x09, 0x06,                    /* Usage (Keyboard) */
	0xA1, 0x01,                    /* Collection (Application) */
	0x85, HIDAPP_KEYBOARD_REPORT_ID, /*   report ID (HIDAPP_KEYBOARD_REPORT_ID) */

	0x75, 0x01,                    /*   Report Size (1) bit */
	0x95, 0x08,                    /*   Report Count (8) */
	0x05, 0x07,                    /*   Usage Page (Key Codes) */
	0x19, 0xe0,                    /*   Usage Minimum (224) */
	0x29, 0xe7,                    /*   Usage Maximum (231) */
	0x15, 0x00,                    /*   Logical Minimum (0) */
	0x25, 0x01,                    /*   Logical Maximum (1) */
	0x81, 0x02,                    /*   Input (Data, Variable, Absolute) */

	0x95, 0x01,                    /*   Report Count (1) */
	0x75, 0x08,                    /*   Report Size (8) */
	0x81, 0x01,                    /*   Input (Constant) reserved byte(1) */

	0x95, 0x05,                    /*   Report Count (5) */
	0x75, 0x01,                    /*   Report Size (1) */
	0x05, 0x08,                    /*   Usage Page (Page# for LEDs) */
	0x19, 0x01,                    /*   Usage Minimum (1) */
	0x29, 0x05,                    /*   Usage Maximum (5) */
	0x91, 0x02,                    /*   Output (Data, Variable, Absolute), Led report */

	0x95, 0x01,                    /*   Report Count (1) */
	0x75, 0x03,                    /*   Report Size (3) */
	0x91, 0x01,                    /*   Output (Constant), Led report padding */

	0x95, 0x06,                    /*   Report Count (6) */
	0x75, 0x08,                    /*   Report Size (8) */
	0x15, 0x00,                    /*   Logical Minimum (0) */
	0x25, 0x65,                    /*   Logical Maximum (101) */
	0x05, 0x07,                    /*   Usage Page (Key codes) */
	0x19, 0x00,                    /*   Usage Minimum (0) */
	0x29, 0x65,                    /*   Usage Maximum (101) */
	0x81, 0x00,                    /*   Input (Data, Array) Key array(6 bytes) */
	0xC0,                          /* End Collection (Application) */

	0x05, 0x01,                    /* USAGE_PAGE (Generic Desktop) */
	0x09, 0x02,                    /* USAGE (Mouse) */
	0xa1, 0x01,                    /* COLLECTION (Application) */
	0x85, HIDAPP_MOUSE_REPORT_ID,  /*   report ID (HIDAPP_MOUSE_REPORT_ID) */
	0x09, 0x01,                    /*   USAGE (Pointer) */
	0xa1, 0x00,                    /*   COLLECTION (Physical) */
	0x95, 0x03,                    /*     REPORT_COUNT (3) */
	0x75, 0x01,                    /*     REPORT_SIZE (1) */
	0x05, 0x09,                    /*     USAGE_PAGE (Button) */
	0x19, 0x01,                    /*     USAGE_MINIMUM (Button 1) */
	0x29, 0x03,                    /*     USAGE_MAXIMUM (Button 3) */
	0x15, 0x00,                    /*     LOGICAL_MINIMUM (0) */
	0x25, 0x01,                    /*     LOGICAL_MAXIMUM (1) */
	0x81, 0x02,                    /*     INPUT (Data, Variable, Absolute) */
	0x95, 0x01,                    /*     REPORT_COUNT (1) */
	0x75, 0x05,                    /*     REPORT_SIZE (5) */
	0x81, 0x01,                    /*     INPUT (Constant) */
	0x75, 0x08,                    /*     REPORT_SIZE (8) */
	0x95, 0x02,                    /*     REPORT_COUNT (2) */
	0x05, 0x01,                    /*     USAGE_PAGE (Generic Desktop) */
	0x09, 0x30,                    /*     USAGE (X) */
	0x09, 0x31,                    /*     USAGE (Y) */
	0x15, 0x81,                    /*     LOGICAL_MINIMUM (-127) */
	0x25, 0x7f,                    /*     LOGICAL_MAXIMUM (127) */
	0x81, 0x06,                    /*     INPUT (Data, Variable, Relative) */
	0xc0,                          /*   End Collection (Physical) */
	0xc0                           /* End Collection (Application) */
#else
	//keyboard report in
	0x05, 0x01,                          // Usage Pg (Generic Desktop)
	0x09, 0x06,                          // Usage (Keyboard)
	0xA1, 0x01,                          // Collection: (Application)
	0x85, HIDAPP_KEYBOARD_REPORT_ID,     // Report Id (keyboard)

	0x05, 0x07,                          // Usage Pg (Key Codes)
	0x19, 0xE0,                          // Usage Min (224)  VK_CTRL:0xe0
	0x29, 0xE7,                          // Usage Max (231)  VK_RWIN:0xe7
	0x15, 0x00,                          // Log Min (0)
	0x25, 0x01,                          // Log Max (1)

				                         // Modifier byte
	0x75, 0x01,                          // Report Size (1)   1 bit * 8
	0x95, 0x08,                          // Report Count (8)
	0x81, 0x02,                          // Input: (Data, Variable, Absolute)

				                         // Reserved byte
	0x95, 0x01,                          // Report Count (1)
	0x75, 0x08,                          // Report Size (8)
	0x81, 0x01,                          // Input: (static constant)

	//keyboard output
	//5 bit led ctrl: NumLock CapsLock ScrollLock Compose kana
	0x95, 0x05,                          //Report Count (5)
	0x75, 0x01,                          //Report Size (1)
	0x05, 0x08,                          //Usage Pg (LEDs )
	0x19, 0x01,                          //Usage Min
	0x29, 0x05,                          //Usage Max
	0x91, 0x02,                          //Output (Data, Variable, Absolute)
	//3 bit reserved
	0x95, 0x01,                          //Report Count (1)
	0x75, 0x03,                          //Report Size (3)
	0x91, 0x01,                          //Output (static constant)

	// Key arrays (6 bytes)
	0x95, 0x06,                          // Report Count (6)
	0x75, 0x08,                          // Report Size (8)
	0x15, 0x00,                          // Log Min (0)
	0x25, 0xF1,                          // Log Max (241)
	0x05, 0x07,                          // Usage Pg (Key Codes)
	0x19, 0x00,                          // Usage Min (0)
	0x29, 0xf1,                          // Usage Max (241)
	0x81, 0x00,                          // Input: (Data, Array)

	0xC0,                            // End Collection

	//consumer report in
	0x05, 0x0C,                           // Usage Page (Consumer)
	0x09, 0x01,                           // Usage (Consumer Control)
	0xA1, 0x01,                           // Collection (Application)
	0x85, HIDAPP_REMOTE_REPORT_ID,        //     Report Id

	0x75,0x10,                            //global, REPORT_SIZE (16) bits
	0x95,0x01,                            //global, REPORT_COUNT (1)
	0x15,0x01,                            //global, logic min  0x01
	0x26,0x8c,0x02,                       //global, logic max  0x28c
	0x19,0x01,                            //local,  usage min   0x01
	0x2a,0x8c,0x02,                       //local,  usage max   0x28c
	0x81,0x00,                            //main,   input data, varible, absolute

	0xc0,                                 //main, end collection
#endif
};
static const uint16_t hidReportMapLen = sizeof(hidReportMap);

/*! HID External Report Reference Descriptor */
static const uint8_t hidExtReport[] = {UINT16_TO_BYTES(ATT_UUID_BATTERY_LEVEL)};
static const uint16_t hidExtReportLen = sizeof(hidExtReport);


/*! HID Control Point Characteristic */
static const uint8_t hidCtrlPointProp[] = {ATT_PROP_WRITE_NO_RSP, UINT16_TO_BYTES(HID_CONTROL_POINT_HDL), UINT16_TO_BYTES(ATT_UUID_HID_CONTROL_POINT)};
static const uint16_t hidCtrlPointPropLen = sizeof(hidCtrlPointProp);

/*! HID Control Point Value */
static uint8_t hidCtrlPointVal[] = {0};
static const uint16_t hidCtrlPointValLen = sizeof(hidCtrlPointVal);


/*! HID Boot Keyboard In Characteristic */
static const uint8_t hidBootKeyInProp[] = {ATT_PROP_READ|ATT_PROP_NOTIFY,
		                                  UINT16_TO_BYTES(HID_KEYBOARD_BOOT_IN_HDL),
		                                  UINT16_TO_BYTES(ATT_UUID_HID_BOOT_KEYBOARD_IN)};
static const uint16_t hidBootKeyInPropLen= sizeof(hidBootKeyInProp);

/*! HID Boot Keyboard In Value */
static uint8_t hidBootKeyInVal[HID_MAX_REPORT_LEN];
static uint16_t hidBootKeyInValLen = sizeof(hidBootKeyInVal);

/*! HID Boot Keyboard In client characteristic configuration */
static uint8_t hidBootKeyInCccd[] = {UINT16_TO_BYTES(0x0000)};
static const uint16_t hidBootKeyInCccdLen = sizeof(hidBootKeyInCccd);


/*! HID Boot Keyboard Out Characteristic */
static const uint8_t hidBootKeyOutProp[] = {ATT_PROP_READ|ATT_PROP_WRITE|ATT_PROP_WRITE_NO_RSP,
		                                   UINT16_TO_BYTES(HID_KEYBOARD_BOOT_OUT_HDL),
		                                   UINT16_TO_BYTES(ATT_UUID_HID_BOOT_KEYBOARD_OUT)};
static const uint16_t hidBootKeyOutPropLen = sizeof(hidBootKeyOutProp);

/*! HID Boot Keyboard Out Value */
static uint8_t hidBootKeyOutVal[HID_MAX_REPORT_LEN];
static uint16_t hidBootKeyOutValLen = sizeof(hidBootKeyOutVal);


/*! HID Boot Mouse In Characteristic */
static const uint8_t hidBootMouseInProp[] = {ATT_PROP_READ | ATT_PROP_NOTIFY, UINT16_TO_BYTES(HID_MOUSE_BOOT_IN_HDL), UINT16_TO_BYTES(ATT_UUID_HID_BOOT_MOUSE_IN)};
static const uint16_t hidBootMouseInPropLen = sizeof(hidBootMouseInProp);

/*! HID Boot Mouse In Value */
static uint8_t hidBootMouseInVal[HID_MAX_REPORT_LEN];
static uint16_t hidBootMouseInValLen = sizeof(hidBootMouseInVal);

/*! HID Boot Mouse In client characteristic configuration */
static uint8_t hidBootMouseInCccd[] = {UINT16_TO_BYTES(0x0000)};
static const uint16_t hidBootMouseInCccdLen = sizeof(hidBootMouseInCccd);


/*! HID Input Report #1 Characteristic */
static const uint8_t hidIRep1Prop[] = {ATT_PROP_READ | ATT_PROP_NOTIFY,
		                               UINT16_TO_BYTES(HID_INPUT_REPORT_1_HDL),
		                               UINT16_TO_BYTES(ATT_UUID_HID_REPORT)};
static const uint16_t hidIRep1PropLen = sizeof(hidIRep1Prop);

/*! HID Input Report Value */
static uint8_t hidIRep1Val[HID_MAX_REPORT_LEN];
static uint16_t hidIRep1ValLen = sizeof(hidIRep1Val);

/*! HID Input Report client characteristic configuration */
static uint8_t hidIRep1Cccd[] = {UINT16_TO_BYTES(0x0001)};// 0x0001->notify; 0x0002->indicate
static const uint16_t hidIRep1CccdLen = sizeof(hidIRep1Cccd);

/*! HID Input Report Reference - ID, Type */
static const uint8_t hidIRep1IdMap[] = {HIDAPP_KEYBOARD_REPORT_ID, HID_REPORT_TYPE_INPUT};
static const uint16_t hidIRep1IdMapLen = sizeof(hidIRep1IdMap);


/*! HID Input Report #2 Characteristic */
static const uint8_t hidIRep2Prop[] = {ATT_PROP_READ | ATT_PROP_NOTIFY,
		                               UINT16_TO_BYTES(HID_INPUT_REPORT_2_HDL),
		                               UINT16_TO_BYTES(ATT_UUID_HID_REPORT)};
static const uint16_t hidIRep2PropLen = sizeof(hidIRep2Prop);

/*! HID Input Report Value */
static uint8_t hidIRep2Val[HID_MAX_REPORT_LEN];
static uint16_t hidIRep2ValLen = sizeof(hidIRep2Val);

/*! HID Input Report client characteristic configuration */
static uint8_t hidIRep2Cccd[] = {UINT16_TO_BYTES(0x0001)};// 0x0001->notify; 0x0002->indicate
static const uint16_t hidIRep2CccdLen = sizeof(hidIRep2Cccd);

/*! HID Input Report Reference - ID, Type */
static const uint8_t hidIRep2IdMap[] = {HIDAPP_REMOTE_REPORT_ID, HID_REPORT_TYPE_INPUT};
static const uint16_t hidIRep2IdMapLen = sizeof(hidIRep2IdMap);


/*! HID Input Report #3 Characteristic */
static const uint8_t hidIRep3Prop[] = {ATT_PROP_READ | ATT_PROP_NOTIFY, UINT16_TO_BYTES(HID_INPUT_REPORT_3_HDL), UINT16_TO_BYTES(ATT_UUID_HID_REPORT)};
static const uint16_t hidIRep3PropLen = sizeof(hidIRep3Prop);

/*! HID Input Report Value */
static uint8_t hidIRep3Val[HID_MAX_REPORT_LEN];
static uint16_t hidIRep3ValLen = sizeof(hidIRep3Val);

/*! HID Input Report client characteristic configuration */
static uint8_t hidIRep3Cccd[] = {UINT16_TO_BYTES(0x0001)};// 0x0001->notify; 0x0002->indicate
static const uint16_t hidIRep3CccdLen = sizeof(hidIRep3Cccd);

/*! HID Input Report Reference - ID, Type */
static const uint8_t hidIRep3IdMap[] = {HIDAPP_MOUSE_REPORT_ID, HID_REPORT_TYPE_INPUT};
static const uint16_t hidIRep3IdMapLen = sizeof(hidIRep3IdMap);


/*! HID Output Report Characteristic */
static const uint8_t hidORepProp[] = {ATT_PROP_READ | ATT_PROP_WRITE | ATT_PROP_WRITE_NO_RSP, UINT16_TO_BYTES(HID_OUTPUT_REPORT_HDL), UINT16_TO_BYTES(ATT_UUID_HID_REPORT)};
static const uint16_t hidORepPropLen = sizeof(hidORepProp);

/*! HID Output Report Value */
static uint8_t hidORepVal[HID_MAX_REPORT_LEN];
static uint16_t hidORepValLen = sizeof(hidORepVal);

/*! HID Output Report Reference - ID, Type */
static const uint8_t hidORepIdMap[] = {0x00, HID_REPORT_TYPE_OUTPUT};
static const uint16_t hidORepIdMapLen = sizeof(hidORepIdMap);


/*! HID Feature Report Characteristic */
static const uint8_t hidFRepProp[] = {ATT_PROP_READ | ATT_PROP_WRITE, UINT16_TO_BYTES(HID_FEATURE_REPORT_HDL), UINT16_TO_BYTES(ATT_UUID_HID_REPORT)};
static const uint16_t hidFRepPropLen = sizeof(hidFRepProp);

/*! HID Feature Report Value */
static uint8_t hidFRepVal[HID_MAX_REPORT_LEN];
static uint16_t hidFRepValLen = sizeof(hidFRepVal);

/*! HID Feature Report Reference - ID, Type */
static const uint8_t hidFRepIdMap[] = {0x00, HID_REPORT_TYPE_FEATURE};
static const uint16_t hidFRepIdMapLen = sizeof(hidFRepIdMap);


/*! HID Protocol Mode Characteristic */
static const uint8_t hidPmProp[] = {ATT_PROP_READ | ATT_PROP_WRITE_NO_RSP,
		                            UINT16_TO_BYTES(HID_PROTOCOL_MODE_HDL),
		                            UINT16_TO_BYTES(ATT_UUID_HID_PROTOCOL_MODE)};
static const uint16_t hidPmPropLen = sizeof(hidPmProp);

/*! HID Protocol Mode Value */
static uint8_t hidPmVal[] = {HID_PROTOCOL_MODE_REPORT};
static const uint16_t hidPmValLen = sizeof(hidPmVal);


/*! Attribute list for HID group */
static const AttsAttr_t hidAttrs[] =
{
  /* HID Service Declaration */
  {
    primSvcUuid,
    (uint8_t *) hidSvc,
    (uint16_t *) &hidSvcLen,
    sizeof(hidSvc),
    0,
    ATTS_PERMIT_READ
  },

  /* HID info */
  {
    charDecUuid,
    (uint8_t *) hidInfoProp,
    (uint16_t *) &hidInfoPropLen,
    sizeof(hidInfoProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidInfoUuid,
    (uint8_t *) hidInfoVal,
    (uint16_t *) &hidInfoValLen,
    sizeof(hidInfoVal),
    0,
    HID_SEC_PERMIT_READ
  },

  /* HID report map */
  {
    charDecUuid,
    (uint8_t *) hidReportMapProp,
    (uint16_t *) &hidReportMapPropLen,
    sizeof(hidReportMapProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidReportMapUuid,
    (uint8_t *) hidReportMap,
    (uint16_t *) &hidReportMapLen,
    HID_MAX_REPORT_MAP_LEN,
    ATTS_SET_VARIABLE_LEN,
    HID_SEC_PERMIT_READ
  },
  {
    hidExtReportUuid,
    (uint8_t *) hidExtReport,
    (uint16_t *) &hidExtReportLen,
    sizeof(hidExtReport),
    0,
    HID_SEC_PERMIT_READ
  },

  /* HID control point */
  {
    charDecUuid,
    (uint8_t *) hidCtrlPointProp,
    (uint16_t *) &hidCtrlPointPropLen,
    sizeof(hidCtrlPointProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidCtrlPointUuid,
    (uint8_t *) hidCtrlPointVal,
    (uint16_t *) &hidCtrlPointValLen,
    sizeof(hidCtrlPointVal),
    0,//ATTS_SET_WRITE_CBACK,
    HID_SEC_PERMIT_WRITE
  },

  /* HID boot keyboard in */
  {
    charDecUuid,
    (uint8_t *) hidBootKeyInProp,
    (uint16_t *) &hidBootKeyInPropLen,
    sizeof(hidBootKeyInProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidBootKeyInUuid,
    (uint8_t *) hidBootKeyInVal,
    (uint16_t *) &hidBootKeyInValLen,
    sizeof(hidBootKeyInVal),
    ATTS_SET_VARIABLE_LEN,
    HID_SEC_PERMIT_READ
  },
  {
    clientCharCfgUuid,
    (uint8_t *) hidBootKeyInCccd,
    (uint16_t *) &hidBootKeyInCccdLen,
    sizeof(hidBootKeyInCccd),
    ATTS_SET_CCC,
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  },

  /* HID boot keyboard out */
  {
	charDecUuid,
    (uint8_t *) hidBootKeyOutProp,
    (uint16_t *) &hidBootKeyOutPropLen,
    sizeof(hidBootKeyOutProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidBootKeyOutUuid,
    (uint8_t *) hidBootKeyOutVal,
    (uint16_t *) &hidBootKeyOutValLen,
    sizeof(hidBootKeyOutVal),
    ATTS_SET_VARIABLE_LEN,//(ATTS_SET_WRITE_CBACK | ATTS_SET_VARIABLE_LEN),
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  },

  /* HID boot mouse input */
  {
	charDecUuid,
    (uint8_t *) hidBootMouseInProp,
    (uint16_t *) &hidBootMouseInPropLen,
    sizeof(hidBootMouseInProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidBootMouseInUuid,
    (uint8_t *) hidBootMouseInVal,
    (uint16_t *) &hidBootMouseInValLen,
    sizeof(hidBootMouseInVal),
    ATTS_SET_VARIABLE_LEN,
    HID_SEC_PERMIT_READ
  },
  {
    clientCharCfgUuid,
    (uint8_t *) hidBootMouseInCccd,
    (uint16_t *) &hidBootMouseInCccdLen,
    sizeof(hidBootMouseInCccd),
    ATTS_SET_CCC,
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  },

  /* HID input report 1 */
  {
	charDecUuid,
    (uint8_t *) hidIRep1Prop,
    (uint16_t *) &hidIRep1PropLen,
    sizeof(hidIRep1Prop),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidReportUuid,
    (uint8_t *) hidIRep1Val,
    (uint16_t *) &hidIRep1ValLen,
    sizeof(hidIRep1Val),
    ATTS_SET_VARIABLE_LEN,
    HID_SEC_PERMIT_READ
  },
  {
    clientCharCfgUuid,
    (uint8_t *) hidIRep1Cccd,
    (uint16_t *) &hidIRep1CccdLen,
    sizeof(hidIRep1Cccd),
    ATTS_SET_CCC,
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  },
  {
    hidReportIdMapUuid,
    (uint8_t *) hidIRep1IdMap,
    (uint16_t *) &hidIRep1IdMapLen,
    sizeof(hidIRep1IdMap),
    0,
    HID_SEC_PERMIT_READ
  },

  /* HID input report 2 */
  {
    charDecUuid,
    (uint8_t *) hidIRep2Prop,
    (uint16_t *) &hidIRep2PropLen,
    sizeof(hidIRep2Prop),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidReportUuid,
    (uint8_t *) hidIRep2Val,
    (uint16_t *) &hidIRep2ValLen,
    sizeof(hidIRep2Val),
    ATTS_SET_VARIABLE_LEN,
    HID_SEC_PERMIT_READ
  },
  {
    clientCharCfgUuid,
    (uint8_t *) hidIRep2Cccd,
    (uint16_t *) &hidIRep2CccdLen,
    sizeof(hidIRep2Cccd),
    ATTS_SET_CCC,
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  },
  {
    hidReportIdMapUuid,
    (uint8_t *) hidIRep2IdMap,
    (uint16_t *) &hidIRep2IdMapLen,
    sizeof(hidIRep2IdMap),
    0,
    HID_SEC_PERMIT_READ
  },

  /* HID input report 3 */
  {
    charDecUuid,
    (uint8_t *) hidIRep3Prop,
    (uint16_t *) &hidIRep3PropLen,
    sizeof(hidIRep3Prop),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidReportUuid,
    (uint8_t *) hidIRep3Val,
    (uint16_t *) &hidIRep3ValLen,
    sizeof(hidIRep3Val),
    ATTS_SET_VARIABLE_LEN,
    HID_SEC_PERMIT_READ
  },
  {
    clientCharCfgUuid,
    (uint8_t *) hidIRep3Cccd,
    (uint16_t *) &hidIRep3CccdLen,
    sizeof(hidIRep3Cccd),
    ATTS_SET_CCC,
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  },
  {
    hidReportIdMapUuid,
    (uint8_t *) hidIRep3IdMap,
    (uint16_t *) &hidIRep3IdMapLen,
    sizeof(hidIRep3IdMap),
    0,
    HID_SEC_PERMIT_READ
  },

  /* HID output report */
  {
    charDecUuid,
    (uint8_t *) hidORepProp,
    (uint16_t *) &hidORepPropLen,
    sizeof(hidORepProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidReportUuid,
    (uint8_t *) hidORepVal,
    (uint16_t *) &hidORepValLen,
    sizeof(hidORepVal),
    0,//(ATTS_SET_WRITE_CBACK | ATTS_SET_VARIABLE_LEN),
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  },
  {
    hidReportIdMapUuid,
    (uint8_t *) hidORepIdMap,
    (uint16_t *) &hidORepIdMapLen,
    sizeof(hidORepIdMap),
    0,
    HID_SEC_PERMIT_READ
  },

  /* HID feature report */
  {
    charDecUuid,
    (uint8_t *) hidFRepProp,
    (uint16_t *) &hidFRepPropLen,
    sizeof(hidFRepProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidReportUuid,
    (uint8_t *) hidFRepVal,
    (uint16_t *) &hidFRepValLen,
    sizeof(hidFRepVal),
    0,//(ATTS_SET_WRITE_CBACK | ATTS_SET_VARIABLE_LEN),
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  },
  {
    hidReportIdMapUuid,
    (uint8_t *) hidFRepIdMap,
    (uint16_t *) &hidFRepIdMapLen,
    sizeof(hidFRepIdMap),
    0,
    HID_SEC_PERMIT_READ
  },

  /* HID protocol mode */
  {
    charDecUuid,
    (uint8_t *) hidPmProp,
    (uint16_t *) &hidPmPropLen,
    sizeof(hidPmProp),
    0,
    ATTS_PERMIT_READ
  },
  {
    hidProtocolModeChUuid,
    (uint8_t *) hidPmVal,
    (uint16_t *) &hidPmValLen,
    sizeof(hidPmVal),
    0,//ATTS_SET_WRITE_CBACK,
    (HID_SEC_PERMIT_READ | HID_SEC_PERMIT_WRITE)
  }
};

/*! HID group structure */
AttsGroup_t hidGrp =
{
  NULL,
  (AttsAttr_t *)hidAttrs,
  NULL,
  NULL,
  HID_START_HDL,
  HID_END_HDL
};

uint8_t HID_SendKeyboardValue(uint16_t connHandle, uint8_t *pvalue, uint32_t len)
{
	if(ATTS_CccEnabled(connHandle, HID_INPUT_REPORT_1_CCC_IDX)){
		return ATTS_ValueNotify(connHandle, HID_INPUT_REPORT_1_HDL, pvalue, len);
	}
	return BLE_ERR_ATT_SERVER_NOTIFY_NOT_ENABLED;
}

uint8_t HID_SendCustomValue(uint16_t connHandle, uint8_t *pvalue, uint32_t len)
{
	if(ATTS_CccEnabled(connHandle, HID_INPUT_REPORT_2_CCC_IDX)){
		return ATTS_ValueNotify(connHandle, HID_INPUT_REPORT_2_HDL, pvalue, len);
	}
	return BLE_ERR_ATT_SERVER_NOTIFY_NOT_ENABLED;
}

uint8_t HID_SendMouseValue(uint16_t connHandle, uint8_t *pvalue, uint32_t len)
{
#if 0
	if(ATTS_CccEnabled(connHandle, HID_INPUT_REPORT_3_CCC_IDX)){
		return ATTS_ValueNotify(connHandle, HID_INPUT_REPORT_3_HDL, pvalue, len);
	}
	return BLE_ERR_ATT_SERVER_NOTIFY_NOT_ENABLED;
#else
	return ATTS_ValueNotify(connHandle, HID_INPUT_REPORT_3_HDL, pvalue, len);
#endif
}


#define MOUSE_MAX_DISTANCE  200
#define MOUSE_STEP          4

int x = 0;
int y = 0;

void HID_MouseTestReset(void)
{
	x = 0;
	y = 0;
}

void HID_MoueTestStart(uint16_t connHande)
{
	uint8_t mouse[3] = {0};
	mouse[0] = 0;

	if(x < 200 && y == 0){
		x += MOUSE_STEP;
		mouse[1] = MOUSE_STEP;
		mouse[2] = 0;
	}
	else{//x=200
		if(y < 200 && x==200){
			y += MOUSE_STEP;
			mouse[1] = 0;
			mouse[2] = MOUSE_STEP;
		}
		else{
			if(x > 0 && y==200)
			{
				x -= MOUSE_STEP;
				mouse[1] = -MOUSE_STEP;
				mouse[2] = 0;
			}
			else{
				if(y > 0 && x==0){
					y -= MOUSE_STEP;
					mouse[1] = 0;
					mouse[2] = -MOUSE_STEP;
				}
			}
		}
	}

	//LL_TRACK_INFO("(X:%d, Y:%d)\r\n", x, y);

	HID_SendMouseValue(connHande, mouse, sizeof mouse);
}

